﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Web;
using System.Configuration;


namespace Logger
{

    public static class PathEx
    {

        /// <summary>
        /// Add backupSlash in end
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string strAddBackSlash(string path)
        {
            if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
                path += Path.DirectorySeparatorChar.ToString();

            return path;
        }
        public static string AddBackSlash(this string path)
        {
            if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
                path += Path.DirectorySeparatorChar.ToString();

            return path;
        }
        /// <summary>
        /// Add backupSlash in end
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string strRemoveEndBackSlash(string path)
        {
            if (path.EndsWith(Path.DirectorySeparatorChar.ToString()))
                path = path.Remove(path.Length - 1);

            return path;
        }
        public static string RemoveEndBackSlash(this string path)
        {
            return strRemoveEndBackSlash(path);
        }
        public static string RemoveEndVolumeSeparatorChar(this string path)
        {
            path =strRemoveEndBackSlash(path);
            if (path.EndsWith(Path.VolumeSeparatorChar.ToString()))
                path = path.Remove(path.Length - 1);

            return path;
        }
        /// <summary>
        /// return Path.Combine(path1.AddBackSlash(), "??" + path2).Replace("??", "");
        /// </summary>
        /// <param name="path1"></param>
        /// <param name="path2"></param>
        /// <returns></returns>
        public static string Combine(string path1, string path2)
        {
            return Path.Combine(strAddBackSlash(path1), path2);
        }


        public static string CombineAndRemoveEndVolumeSeparatorChar(string path1, string path2, bool bCallBase)
        {
            return bCallBase ? Path.Combine(strAddBackSlash(path1), path2) : Path.Combine(strAddBackSlash(path1),strRemoveEndBackSlash(path2));
        }


        public static string CombinePaths(params object[] paths)
        {
            return Convert.ToString(paths.Aggregate((x, y) => System.IO.Path.Combine(strAddBackSlash(x.ToString()), y.ToString())));
        }

        public static bool IsPathEquals(this string path1, string path2)
        {
            return (strAddBackSlash(path1).ToLower() == strAddBackSlash(path2).ToLower());
        }


        public static string CombineEx(string path1, string path2)
        {
            path1 = path1.TrimEnd('\\');
            path2 = path2.TrimStart('\\');
            return string.Format("{0}\\{1}", path1, path2);
        }
    }

    public static class cGlobalSettings
    {

        //static string formattedLogMsgUser = string.Format(" |\t RequestId:{0} \t UserId:{1} \t UserMachineId:{2} \t {3}::{4}: \t{5} \t{6} ");
        //static string formattedLogMsg = string.Format(" |\t RequestId:{0} \t {1}::{2}: \t{3} \t{4} ");

        static cGlobalSettings()
        {
            InitLogger();
        }

        /// <summary>
        /// Error Log Path
        /// </summary>



        public static string ServerName
        {
            get
            {
                try
                {
                    return HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
                }
                catch (System.Exception ex)
                {
                    ;
                }
                return string.Empty;
            }
        }

        public static string LogPath
        {
            get
            {
                try
                {
                    string dirPath = PathEx.CombinePaths
                        (
                        AppVirtualDirectory.VirtualDirPath,
                        HttpContext.Current.Request.ServerVariables["SERVER_NAME"]
                        );
                    return PathEx.Combine(dirPath, (Convert.ToString(HttpRuntime.AppDomainAppVirtualPath).Replace("/", "")));
                }
                catch (System.Exception)
                {
                    ;
                }

                return string.Empty;
            }

        }

        public static string LogFileName
        {
            get
            {
                try
                {
                    return string.Format("{0}.txt", string.Format("{0}_{1}", DateTime.UtcNow.ToString("yyyy_MM_dd"), (Convert.ToString(HttpRuntime.AppDomainAppVirtualPath).Replace("/", ""))));
                }
                catch (System.Exception)
                {
                    ;
                }

                return string.Empty;
            }

        }

        public static string SuccessLogFileName
        {
            get
            {
                try
                {
                    return string.Format("{0}.txt", string.Format("{0}_Success_{1}", DateTime.UtcNow.ToString("yyyy_MM_dd"), (Convert.ToString(HttpRuntime.AppDomainAppVirtualPath).Replace("/", ""))));
                }
                catch (System.Exception)
                {
                    ;
                }

                return string.Empty;
            }

        }

        public static string UnhandledLogFileName
        {
            get
            {
                try
                {
                    return string.Format("{0}.txt", string.Format("{0}_Unhandled_{1}", DateTime.UtcNow.ToString("yyyy_MM_dd"), (Convert.ToString(HttpRuntime.AppDomainAppVirtualPath).Replace("/", ""))));
                }
                catch (System.Exception)
                {
                    ;
                }

                return string.Empty;
            }

        }

        public static cLogger oLogger = null;
        public static void InitLogger()
        {
            try
            {
                oLogger = new cLogger(LogPath, LogFileName, HttpRuntime.AppDomainAppVirtualPath);
            }
            catch (System.Exception)
            {
                ;
            }
        }
    }






    ///<summary>
    ///for manging error logging functionality
    ///</summary>
    public class cLogger : IDisposable
    {

        private string m_LogPath;
        private bool m_Logging;
        private string m_Area;
        private string m_ClassName;
        private string m_FunctionName;
        private string _sLogFilePathName;
        private string sLogFilePathName
        {
            get { return _sLogFilePathName; }
            set
            {
                _sLogFilePathName = value;
                sLogFilePathDirectory = Path.GetDirectoryName(_sLogFilePathName);
            }
        }
        private string sLogFilePathDirectory;
        private string sLogFileNameWithOutExtension { get; set; }
        private StreamWriter oStreamWriter;

        private bool bverboselog = false;
        //public bool bVerboseLoggingEnabled = false;

        public bool bVerboseLoggingEnabled
        {
            get
            {
                try
                {
                    byte verboseVal = Convert.ToByte(ConfigurationManager.AppSettings["isVerboseEnabled"]);
                    if (verboseVal == 1)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (System.Exception ex)
                {
                    cGlobalSettings.oLogger.WriteLogException("Error while getting isVerboseEnabled key from webconfig", ex);
                    return false;
                }

            }
            set
            {
                bverboselog = value;
            }
        }

        ///<summary>
        ///get set LogPath field
        ///</summary>
        public string LogPath
        {
            get
            {
                return m_LogPath;
            }
            set
            {
                m_LogPath = value;
                if (m_LogPath[m_LogPath.Length - 1].ToString() != @"\") m_LogPath = m_LogPath + @"\";
            }
        }

        ///<summary>
        ///get set Logging field
        ///</summary>
        public bool Logging
        {
            get
            {
                return m_Logging;
            }
            set
            {
                m_Logging = value;
            }
        }

        ///<summary>
        ///get set Area field
        ///</summary>
        public string Area
        {
            get
            {
                return m_Area;
            }
            set
            {
                m_Area = value;
            }
        }

        ///<summary>
        ///get set ClassName field
        ///</summary>
        public string ClassName
        {
            get
            {
                return m_ClassName;
            }
            set
            {
                m_ClassName = value;
            }
        }

        ///<summary>
        ///get set FunctionName field
        ///</summary>
        public string FunctionName
        {
            get
            {
                return m_FunctionName;
            }
            set
            {
                m_FunctionName = value;
            }
        }

        /*
         Code Modified by Sujeet Starts
         */

        public enum LogType
        {
            DisabledLog = 0,
            VerboseLog,
            ExceptionLog,
        }

        public enum LogSource
        {
            EmailWebServiceLogger,
            RbUserPlansUpgrade,
            RbWebsite,
        }

        public static LogSource currentLogType = LogSource.RbWebsite;
        private static string sUserIdFilePath = string.Empty;

        public static readonly Random rand = new Random();
        //Random Request Number
        public static int getRequestedID()
        {
            try
            {
                int rInt = rand.Next(10000, 99999); //for ints
                //int range = 100;
                //double rDouble = rand.NextDouble() * range; //for doubles
                return rInt;
            }
            catch (System.Exception e)
            {
                cGlobalSettings.oLogger.WriteLogException("cLogger::getRequestedID", e);
                return 0;
            }

        }

        public static void WriteToFile(string msg)
        {
            try
            {
                //if (string.IsNullOrEmpty(sLogFilePath))
                //    return;

                //if (!File.Exists(sLogFilePath))
                //{
                //    FileStream fs = new FileStream(sLogFilePath, FileMode.CreateNew, FileAccess.Write);
                //    fs.Close();
                //    fs.Dispose();
                //}
                //StreamWriter sw = new StreamWriter(sLogFilePath, true);
                //sw.WriteLine(string.Format("{2}||{0}|{1}", DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss"), msg, "BetaService Error: "));
                //sw.Close();
                //sw.Dispose();

            }
            catch (Exception ex)
            {

            }
        }

        public static void WriteToFile(string sUserId, string msg)
        {
            try
            {
                //string sLogDirPath = Path.Combine(Path.GetDirectoryName(sLogFilePath), sUserId);
                //if (!Directory.Exists(sLogDirPath))
                //{
                //    Directory.CreateDirectory(sLogDirPath);
                //    sUserIdFilePath = Path.Combine(sLogDirPath, "rightbackupweblog.log");
                //}
                //else
                //{
                //    sUserIdFilePath = Path.Combine(sLogDirPath, "rightbackupweblog.log");
                //}


                //if (!File.Exists(sUserIdFilePath))
                //{
                //    FileStream fs = new FileStream(sUserIdFilePath, FileMode.CreateNew, FileAccess.Write);
                //    fs.Close();
                //    fs.Dispose();
                //}
                //StreamWriter sw = new StreamWriter(sUserIdFilePath, true);
                //sw.WriteLine(string.Format("{0}|{1}", DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss"), msg));
                //sw.Close();
                //sw.Dispose();

            }
            catch (Exception ex)
            {
                //                System.Diagnostics.EventLog.WriteEntry("cRightBackupServer", "In WritetoFile :" + ex.ToString());
            }

        }
        public static void WriteToLogFile(string msg, string currentpagename, string methodname, string actiontodo, bool isVerboseLog)
        {

        }

        public static void IssuesWriteToFile(string msg)
        {


        }

        public static void WriteToLogFile(int nRequestId, string msg, Exception ex, bool isVerboseLog)
        {
            try
            {
                cLogger oLogger = new cLogger();
                string briefErrorMsg = msg;// getErrorMessageInDetail(msg);                

                //Check if Log is of Verbose Type
                if (isVerboseLog)
                {
                    oLogger.WriteLogVerbose(briefErrorMsg);
                }
                else
                {
                    oLogger.WriteLogException(briefErrorMsg, ex);
                }
            }
            catch (System.Exception e)
            {

            }
        }

        //code to generate error message in detail
        public static string getErrorMessageInDetail(string msg)
        {
            Exception ex = null;
            StringBuilder errMsg = new StringBuilder();
            try
            {

                if (ex != null)
                {
                    // Get stack trace for the exception with source file information
                    StackTrace st = null;

                    st = new StackTrace(ex, true);

                    // Get the top stack frame
                    var frame = st.GetFrame(0);
                    // Get the line number from the stack frame
                    var line = frame.GetFileLineNumber();
                    errMsg.AppendLine(string.Format("Exception: ex.StackTrace:{0}", ex.StackTrace));
                    errMsg.AppendLine("");
                    errMsg.AppendLine(string.Format("Exception: Environment.StackTrace:{0}", Environment.StackTrace));
                    errMsg.AppendLine("");
                    errMsg.AppendLine(string.Format("Exception: Full-StackTrace:{0}", GetStackTrace()));
                    errMsg.AppendLine("");
                    errMsg.AppendLine(string.Format("Exception: Message:{0}\text:{1}, Exception Line number:{2}, StackTrace:{3}", msg, ex.ToString(), line, st));
                }
                errMsg.AppendLine(string.Format("\n\n ***************\n\n {0} \n --- \n", msg));

            }
            catch (Exception ex1)
            {
                //WriteToLogFile(ex1.ToString(), this.ToString(), "writeErrorLogs()", "Generating Verbose Error Detail", false);
            }
            return errMsg.ToString();
        }

        public cLogger()
        {

        }

        /*
         Code Modified by Sujeet Ends
         */

        ///<summary>
        ///constructor
        ///</summary>
        public cLogger(string LogPath, string LogFileName, string LogFileNameWithOutExtension)
        {
            try
            {
                //readerWriterLockSlim = new ReaderWriterLockSlim();
                //m_Logging = false;
                m_Logging = true;
                m_LogPath = LogPath;
                sLogFilePathName = PathEx.Combine(m_LogPath, LogFileName); //+ DateTime.Now.ToString("dd-MM-yyyy") + "_" + m_LogFileName;
                sLogFileNameWithOutExtension = LogFileNameWithOutExtension;
                if (!Directory.Exists(m_LogPath))
                {
                    Directory.CreateDirectory(m_LogPath);
                }
                if (!File.Exists(sLogFilePathName))
                {
                    FileStream fs = new FileStream(sLogFilePathName, FileMode.CreateNew, FileAccess.Write);
                    fs.Close();
                    fs.Dispose();
                }

            }
            catch (Exception ex)
            {

            }
        }
        ~cLogger()
        {
            Dispose(false);
        }

        public bool WriteLogVerbose(string format, params object[] args)
        {
            if (bVerboseLoggingEnabled)
            {
                try
                {
                    /*bkThread.InvokeInBackground(() => */
                    l_WriteLog(string.Format(format, args))/*)*/;
                    //return WriteLogVerbose(string.Format(format, args));
                }
                catch (System.Exception)
                {
                    ;
                }

            }
            return true;
        }


        public bool WriteLogVerbose(string sMessage, bool isSuccessLog = false)
        {
            if (bVerboseLoggingEnabled)
            {
                return WriteLogVerbose(sMessage, false, isSuccessLog);
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// this is to write the verbose log of DLL
        /// </summary>
        /// <param name="sMessage"></param>
        /// <returns></returns>
        public bool WriteLogVerbose(string sMessage, bool bEncypted, bool isSuccessLog = false)
        {
            if (bVerboseLoggingEnabled)
            {
                return WriteLog(sMessage, bEncypted, isSuccessLog);
            }
            return true;
        }

        private static string WhoCalledMe()
        {
            try
            {
                StackTrace stackTrace = new StackTrace();
                StackFrame stackFrame = stackTrace.GetFrame(4);
                MethodBase methodBase = stackFrame.GetMethod();
                Console.WriteLine(" Parent Method Name {0} ", methodBase.Name);
                return string.Format("MethodName={0}; FileName={1};LineNumber={2};FileColumnNumber={3};", methodBase.Name, stackFrame.GetFileName(), stackFrame.GetFileLineNumber(), stackFrame.GetFileColumnNumber());
            }
            catch (System.Exception ex)
            {
                return ex.ToString();
            }

        }

        private static string GetStackTrace()
        {
            StringBuilder sb = new StringBuilder();
            // I WILL LOG THE EXCEPTION object "EX" here ! but ex.StackTrace is truncated!
            StackTrace st = new StackTrace(true);
            for (int i = 0; i < st.FrameCount; i++)
            {
                // Note that high up the call stack, there is only
                // one stack frame.
                StackFrame sf = st.GetFrame(i);
                sb.AppendLine(sf.ToString().Replace("\r\n", "")/* + "Params:"+sf.GetMethod().GetParameters()*//*string.Format("MethodName={0}; FileName={1};LineNumber={2};FileColumnNumber={3};", sf.GetMethod(), sf.GetFileName(), sf.GetFileLineNumber(), sf.GetFileColumnNumber())*/);
            }

            return sb.ToString();
        }

        public bool WriteLogException(string message, Exception ex, bool isUnHandledException = false)
        {
            try
            {
                if (isUnHandledException)
                {
                    return l_WriteLog(message, false, false, true);
                }
                else
                    return WriteLog(string.Format("Exception: Message:{0}\text:{1}", message, ex.ToString()), isUnHandledException);
            }
            catch (Exception ex1)
            {
                Trace.WriteLine(ex1.Message);
                return false;
            }

        }

        public bool WriteLog(string sMessage, bool isSuccessLog = false)
        {
            bool bEncypted = false;
            return WriteLog(sMessage, bEncypted, isSuccessLog);
        }

        public bool WriteLog(string sMessage, bool bEncypted, bool isSuccessLog = false)
        {
            /*bkThread.InvokeInBackground(()=>*/
            l_WriteLog(sMessage, bEncypted, isSuccessLog)/*)*/;

            return true;
        }

        public bool WriteLogWithNoBkThread(string sMessage)
        {
            l_WriteLog(sMessage);

            return true;
        }

        public string GetLogFileNewName()
        {
            if (string.IsNullOrEmpty(sLogFilePathDirectory) || string.IsNullOrEmpty(sLogFileNameWithOutExtension))
            {
                return string.Empty;
            }

            return PathEx.Combine(sLogFilePathDirectory, sLogFileNameWithOutExtension + DateTime.Now.ToString("_ddMMyyyy_hhmmss_fff") + ".txt");
        }

        ///<summary>
        ///write log using default filepath name
        ///</summary>
        ///<param name="sMessage">message to be written</param>
        public bool l_WriteLog(string sMessage, bool isSuccessLog = false)
        {
            bool bEncypted = false;
            return l_WriteLog(sMessage, bEncypted, isSuccessLog);
        }


        ///<summary>
        ///write log using default filepath name
        ///</summary>
        ///<param name="sMessage">message to be written</param>
        public bool l_WriteLog(string sMessage, bool bEncypted, bool isSuccessLog = false, bool isUnhandledException = false)
        {
            try
            {
                //cGlobalSettings.readerWriterLogLockSlim.EnterWriteLock();

                //#if DEBUG
                //                System.Diagnostics.Debug.WriteLine(string.Format("{0}|{1}", DateTime.Now.ToLocalTime(), sMessage));
                //#endif

                sLogFilePathDirectory = cGlobalSettings.LogPath;

                if (isUnhandledException)
                    _sLogFilePathName = cGlobalSettings.UnhandledLogFileName;
                else if (isSuccessLog)
                    _sLogFilePathName = cGlobalSettings.SuccessLogFileName;
                else
                    _sLogFilePathName = cGlobalSettings.LogFileName;

                sLogFilePathName = PathEx.CombinePaths(sLogFilePathDirectory, _sLogFilePathName);

                if (string.IsNullOrEmpty(sLogFilePathDirectory) || string.IsNullOrEmpty(sLogFilePathName))
                {
                    return false;
                }

                bool bResult = true;

                try
                {
                    //if (!m_Logging) return true;


                    if (!Directory.Exists(sLogFilePathDirectory)) Directory.CreateDirectory(sLogFilePathDirectory);

                    if (File.Exists(sLogFilePathName))
                    {
                        FileInfo fi = new FileInfo(sLogFilePathName);
                        long fileLength = fi.Length;//NativeMethodsExtensions.GetFileSize(sLogFilePathName);
                        if (fileLength > (20 * 1024 * 1024)) // MAX SIZE OF A SINGLE LOG FILE
                        {
                            string sLogFilePathNewName = GetLogFileNewName();

                            // rename old file
                            File.Move(sLogFilePathName, sLogFilePathNewName);
                        }
                    }

                    if (string.IsNullOrEmpty(sLogFilePathName)) return false;

                    if (!File.Exists(sLogFilePathName))
                    {


                        FileStream fs = new FileStream(sLogFilePathName, FileMode.CreateNew, FileAccess.Write);
                        fs.Close();
                        fs.Dispose();
                    }


                    oStreamWriter = File.AppendText(sLogFilePathName);
                    oStreamWriter.WriteLine(string.Format("{0}|{2}", DateTime.Now.ToLocalTime(), 1/*cGlobalSettings.nUserMachineId*/, bEncypted ? ("<enc>" + EncryptString(sMessage) + "</enc>") : sMessage));
                    oStreamWriter.Close();


                }
                catch //(Exception oEx)
                {
                    bResult = false;
                    //throw;
                }
                return bResult;
            }
            finally
            {
                //cGlobalSettings.readerWriterLogLockSlim.SafeExitWriteLock();
            }
        }


        public string EncryptString(string Value)
        {
#if DEBUG
            return Value;
#endif
            StringBuilder res = new StringBuilder(1024);
            char[] ValueChar = Value.ToCharArray();
            for (int i = 0; i < ValueChar.Length; i++)
            {
                res.Append((char)(~(ValueChar[i])));
            }
            return res.ToString();
        }

        public string EncryptAnsiString(string Value)
        {

            StringBuilder res = new StringBuilder(1024);
            char[] ValueChar = Value.ToCharArray();
            for (int i = 0; i < ValueChar.Length; i++)
            {
                res.Append((char)(~(ValueChar[i])));
            }
            return res.ToString();
        }

        #region IDisposable Members

        public void Dispose()
        {
            //bkThread.Stop();
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        private void Dispose(bool bDisposing)
        {
            if (oStreamWriter != null)
            {
                oStreamWriter.Dispose();
                oStreamWriter = null;
            }
        }
        #endregion
    }



    public static class AppVirtualDirectory
    {

        public static string ServerName
        {
            get
            {
                try
                {
                    return HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
                }
                catch (System.Exception e)
                {
                    cGlobalSettings.oLogger.WriteLogException("AppVirtualDirectory::ServerName", e);
                }
                return string.Empty;
            }
        }

        public static string VirtualDirPath
        {
            get
            {
                try
                {

                    //NameValueCollection coll;


                    // Load ServerVariable collection into NameValueCollection object.
                    //coll = HttpContext.Current.Request.ServerVariables; 

                    string Virtual_Dir_Path = DBClass.getWebConfigData("ErrorLogVirtualDirectoryName");
                    //string sPath = HttpContext.Current.Request.MapPath(Virtual_Dir_Path);
                    string sPath = HttpContext.Current.Server.MapPath(string.Format("/{0}", Virtual_Dir_Path));
                    if (!Directory.Exists(sPath))
                        Directory.CreateDirectory(sPath);

                    //string virtualDirPath = Path.GetDirectoryName(HttpRuntime.AppDomainAppPath);
                    //virtualDirPath = string.IsNullOrEmpty(virtualDirPath) ? string.Empty
                    //    : Path.GetFileNameWithoutExtension((virtualDirPath.LastIndexOf("\\") == (virtualDirPath.Length - 1)) ? virtualDirPath.Substring(0, virtualDirPath.Length - 1) : virtualDirPath);
                    //return virtualDirPath;
                    //string virtualDirPath = sPath;
                    return sPath;
                }
                catch (System.Exception ex)
                {
                    cLogger.WriteToLogFile("unable to found virtual directory for writing error log", "App_Code/cErrorHandler.cs", "class AppVirtualDirectory", "Looking for virtual directory", false);
                }

                return string.Empty;

            }
        }


        public static string VirtualDirName
        {
            get
            {
                try
                {
                    string virtualDirPath = Path.GetDirectoryName(HttpRuntime.AppDomainAppPath);
                    virtualDirPath = string.IsNullOrEmpty(virtualDirPath) ? string.Empty
                        : Path.GetFileNameWithoutExtension((virtualDirPath.LastIndexOf("\\") == (virtualDirPath.Length - 1)) ? virtualDirPath.Substring(0, virtualDirPath.Length - 1) : virtualDirPath);
                    return virtualDirPath;
                }
                catch (System.Exception ex)
                {
                    cLogger.WriteToLogFile("unable to found virtual directory for writing error log", "App_Code/cErrorHandler.cs", "class AppVirtualDirectory", "Looking for virtual directory", false);
                }

                return string.Empty;

            }
        }
    }
}